package com.cloud.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cloud.common.domain.Result;
import com.cloud.common.enums.AxisTypes;
import com.cloud.exception.CustomException;
import com.cloud.system.entity.SysAxis;
import com.cloud.system.service.ISysAxisService;
import com.cloud.utils.ExcelPoiUtils;
import com.cloud.utils.GPSUtils;
import com.cloud.utils.ServletUtils;
import com.cloud.utils.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.List;

/**
 * 坐标转换工具
 *
 * @author yzj
 */
@Service
public class SysAxisServiceImpl implements ISysAxisService {

    /**
     * 根据类型转化坐标
     *
     * @param axis
     * @return
     */
    @Override
    public Result invertAxis(SysAxis axis) {
        if (StringUtils.isNull(axis.getPutAxis()) || StringUtils.isNull(axis.getOutAxis())) {
            return Result.error("转化坐标不能为空");
        }
        if (axis.getPutAxis() == axis.getOutAxis()) {
            return Result.error("选择转化坐标不能相同");
        }
        axisTypeInvert(axis);
        return Result.success("转换成功", axis);
    }

    /**
     * 根据模板信息导入数据
     *
     * @param file
     */
    @Override
    public List<SysAxis> importExcel(MultipartFile file) {
        List<SysAxis> axisList = ExcelPoiUtils.importExcel(file, 1, 1, SysAxis.class);
        if (StringUtils.isNull(axisList) && axisList.size() == 0) {
            throw new CustomException("导入坐标数据不能为空!");
        }
        // 循环转化坐标信息
        for (SysAxis axis : axisList) {
            axisTypeInvert(axis);
        }
        return axisList;
    }

    /**
     * 根据模板信息导出数据
     *
     * @param axisList
     */
    @Override
    public void exportExcel(List<SysAxis> axisList) {
        String titleName = "坐标转换列表";
        ExcelPoiUtils.exportExcel(axisList, titleName, "坐标",
                SysAxis.class, titleName + ".xls", ServletUtils.getResponse());
    }

    /**
     * 根据模板信息导入数据
     */
    @Override
    public Result importJson(Integer putAxis, Integer outAxis, MultipartFile file) {
        JSONObject jsonObject = null;
        try {
            InputStream inputStream = file.getInputStream();
            Reader reader = new InputStreamReader(inputStream, "utf-8");
            int ch = 0;
            StringBuffer stringBuffer = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                stringBuffer.append((char) ch);
            }
            // 关闭文件输出流
            reader.close();
            jsonObject = JSONObject.parseObject(stringBuffer.toString());
            JSONArray jsonArray = jsonObject.getJSONArray("features");
            if (jsonArray.size() <= 0) {
                return Result.error("操作失败:获取Json节点数据失败");
            }
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject2 = jsonArray.getJSONObject(i);
                JSONObject jsonObject3 = jsonObject2.getJSONObject("properties");
                if (jsonObject3.containsKey("center")) {
                    JSONArray jsonArray2 = jsonObject3.getJSONArray("center");
                    double[] axisInfo1 = axisJsonInvert(putAxis, outAxis, jsonArray2);
                    jsonArray2.set(0, axisInfo1[0]);
                    jsonArray2.set(1, axisInfo1[1]);
                }
                if (jsonObject3.containsKey("centroid")) {
                    JSONArray jsonArray3 = jsonObject3.getJSONArray("centroid");
                    double[] axisInfo2 = axisJsonInvert(putAxis, outAxis, jsonArray3);
                    jsonArray3.set(0, axisInfo2[0]);
                    jsonArray3.set(1, axisInfo2[1]);
                }
                JSONObject jsonObject4 = jsonObject2.getJSONObject("geometry");
                if (jsonObject4.containsKey("coordinates")) {
                    JSONArray jsonArray4 = jsonObject4.getJSONArray("coordinates").getJSONArray(0);
                    if (jsonArray4.size() > 1) {
                        for (int j = 0; j < jsonArray4.size(); j++) {
                            JSONArray jsonArray6 = jsonArray4.getJSONArray(j);
                            double[] axisInfo = axisJsonInvert(putAxis, outAxis, jsonArray6);
                            jsonArray6.set(0, axisInfo[0]);
                            jsonArray6.set(1, axisInfo[1]);
                        }
                    } else {
                        JSONArray jsonArray5 = jsonArray4.getJSONArray(0);
                        if (jsonArray5.size() > 0) {
                            for (int z = 0; z < jsonArray5.size(); z++) {
                                JSONArray jsonArray6 = jsonArray5.getJSONArray(z);
                                double[] axisInfo = axisJsonInvert(putAxis, outAxis, jsonArray6);
                                jsonArray6.set(0, axisInfo[0]);
                                jsonArray6.set(1, axisInfo[1]);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return Result.error("操作失败:" + e.getMessage());
        }
        return Result.success("操作成功", jsonObject);
    }

    /**
     * 根据模板信息导出数据
     */
    @Override
    public void exportJson(String geojson) {
        HttpServletResponse response = ServletUtils.getResponse();
        ByteArrayInputStream is = null;
        OutputStream os = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=border.geojson");
            // 创建GeoJson临时文件
            File temp = File.createTempFile("border_", ".geojson");
            temp.deleteOnExit();
            BufferedWriter out = new BufferedWriter(new FileWriter(temp));
            out.write(geojson);
            out.close();
            if (temp.exists()) {
                is = new ByteArrayInputStream(FileUtils.readFileToByteArray(temp));
                os = response.getOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    os.write(buffer, 0, len);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 坐标类型转换类
     */
    private void axisTypeInvert(SysAxis axis) {
        double[] axisInfo = null;
        double rawLon = Double.parseDouble(axis.getRawLon());
        double rawLas = Double.parseDouble(axis.getRawLas());
        // G84/天地图 ==》 高德/腾讯
        if (AxisTypes.G84.getCode() == axis.getPutAxis() && AxisTypes.GAUD.getCode() == axis.getOutAxis()) {
            axisInfo = GPSUtils.Gps84_To_Gcj02(rawLon, rawLas);
            axis.setTarLon(String.valueOf(axisInfo[0]));
            axis.setTarLas(String.valueOf(axisInfo[1]));
            axis.setInvertRemark("G84转高德");
        } else if (AxisTypes.GAUD.getCode() == axis.getPutAxis() && AxisTypes.G84.getCode() == axis.getOutAxis()) {
            axisInfo = GPSUtils.Gcj02_To_Gps84(rawLon, rawLas);
            axis.setTarLon(String.valueOf(axisInfo[0]));
            axis.setTarLas(String.valueOf(axisInfo[1]));
            axis.setInvertRemark("高德转G84");
        } else if (AxisTypes.G84.getCode() == axis.getPutAxis() && AxisTypes.BAIDU.getCode() == axis.getOutAxis()) {
            axisInfo = GPSUtils.gps84_To_bd09(rawLon, rawLas);
            axis.setTarLon(String.valueOf(axisInfo[0]));
            axis.setTarLas(String.valueOf(axisInfo[1]));
            axis.setInvertRemark("G84转百度");
        } else if (AxisTypes.BAIDU.getCode() == axis.getPutAxis() && AxisTypes.G84.getCode() == axis.getOutAxis()) {
            axisInfo = GPSUtils.bd09_To_gps84(rawLon, rawLas);
            axis.setTarLon(String.valueOf(axisInfo[0]));
            axis.setTarLas(String.valueOf(axisInfo[1]));
            axis.setInvertRemark("百度转G84");
        } else if (AxisTypes.GAUD.getCode() == axis.getPutAxis() && AxisTypes.BAIDU.getCode() == axis.getOutAxis()) {
            axisInfo = GPSUtils.Gcj02_To_Bd09(rawLon, rawLas);
            axis.setTarLon(String.valueOf(axisInfo[0]));
            axis.setTarLas(String.valueOf(axisInfo[1]));
            axis.setInvertRemark("高德转百度");
        } else if (AxisTypes.BAIDU.getCode() == axis.getPutAxis() && AxisTypes.GAUD.getCode() == axis.getOutAxis()) {
            axisInfo = GPSUtils.Bd09_To_Gcj02(rawLon, rawLas);
            axis.setTarLon(String.valueOf(axisInfo[0]));
            axis.setTarLas(String.valueOf(axisInfo[1]));
            axis.setInvertRemark("百度转高德");
        } else {
            axis.setInvertRemark("错误");
            if (axis.getPutAxis() == axis.getOutAxis()) {
                axis.setTarLon("坐标转换失败:选择转化坐标不能相同");
            } else {
                axis.setTarLon("坐标转换失败:选择转换类型不存在");
            }
        }
    }

    /**
     * 坐标类型转换类
     */
    private double[] axisJsonInvert(Integer putAxis, Integer outAxis, JSONArray jsonArray) {
        double[] axisInfo = null;
        // G84/天地图 ==》 高德/腾讯
        if (AxisTypes.G84.getCode() == putAxis && AxisTypes.GAUD.getCode() == outAxis) {
            axisInfo = GPSUtils.Gps84_To_Gcj02(jsonArray.getDouble(0), jsonArray.getDouble(1));
        } else if (AxisTypes.GAUD.getCode() == putAxis && AxisTypes.G84.getCode() == outAxis) {
            axisInfo = GPSUtils.Gcj02_To_Gps84(jsonArray.getDouble(0), jsonArray.getDouble(1));
        } else if (AxisTypes.G84.getCode() == putAxis && AxisTypes.BAIDU.getCode() == outAxis) {
            axisInfo = GPSUtils.gps84_To_bd09(jsonArray.getDouble(0), jsonArray.getDouble(1));
        } else if (AxisTypes.BAIDU.getCode() == putAxis && AxisTypes.G84.getCode() == outAxis) {
            axisInfo = GPSUtils.bd09_To_gps84(jsonArray.getDouble(0), jsonArray.getDouble(1));
        } else if (AxisTypes.GAUD.getCode() == putAxis && AxisTypes.BAIDU.getCode() == outAxis) {
            axisInfo = GPSUtils.Gcj02_To_Bd09(jsonArray.getDouble(0), jsonArray.getDouble(1));
        } else if (AxisTypes.BAIDU.getCode() == putAxis && AxisTypes.GAUD.getCode() == outAxis) {
            axisInfo = GPSUtils.Bd09_To_Gcj02(jsonArray.getDouble(0), jsonArray.getDouble(1));
        } else {
            axisInfo[0] = jsonArray.getDouble(0);
            axisInfo[1] = jsonArray.getDouble(1);
        }
        return axisInfo;
    }

}
